/**
 * SSD1306 OLED显示屏驱动
 * 0.96寸 128x64分辨率 I2C接口
 */

#include "ssd1306.h"
#include "stdio.h"
#include "string.h"

// OLED显存
static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8];

// 当前光标位置
static uint8_t SSD1306_CursorX = 0;
static uint8_t SSD1306_CursorY = 0;

// I2C超时定义
#define I2C_TIMEOUT 10000

// 延时函数
static void Delay_us(uint32_t us) {
    uint32_t count = us * 8; // 72MHz时钟
    while (count--) {
        __NOP();
    }
}

// 等待I2C事件
static uint8_t I2C_WaitEvent(I2C_TypeDef* I2Cx, uint32_t event) {
    uint32_t timeout = I2C_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, event)) {
        if (--timeout == 0) return 0;
    }
    return 1;
}

// 发送命令
static void SSD1306_WriteCommand(uint8_t command) {
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return;
    
    I2C_Send7bitAddress(I2C1, SSD1306_I2C_ADDR >> 1, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return;
    
    // 发送命令标志
    I2C_SendData(I2C1, SSD1306_CMD);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return;
    
    // 发送命令
    I2C_SendData(I2C1, command);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return;
    
    I2C_GenerateSTOP(I2C1, ENABLE);
}

// 发送数据
static void SSD1306_WriteData(uint8_t data) {
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return;
    
    I2C_Send7bitAddress(I2C1, SSD1306_I2C_ADDR >> 1, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return;
    
    // 发送数据标志
    I2C_SendData(I2C1, SSD1306_DATA);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return;
    
    // 发送数据
    I2C_SendData(I2C1, data);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return;
    
    I2C_GenerateSTOP(I2C1, ENABLE);
}

// SSD1306初始化
void SSD1306_Init(void) {
    // 基本初始化序列
    SSD1306_WriteCommand(0xAE); // 关闭显示
    
    SSD1306_WriteCommand(0x20); // 设置内存地址模式
    SSD1306_WriteCommand(0x10); // 00:水平寻址模式; 01:垂直寻址模式; 10:页寻址模式(默认)
    
    SSD1306_WriteCommand(0xB0); // 设置页起始地址 (页寻址模式)
    
    SSD1306_WriteCommand(0xC8); // 设置COM输出扫描方向 (C0:正常; C8:反向)
    
    SSD1306_WriteCommand(0x00); // 设置低列地址
    SSD1306_WriteCommand(0x10); // 设置高列地址
    
    SSD1306_WriteCommand(0x40); // 设置显示起始行 (0x40-0x7F)
    
    SSD1306_WriteCommand(0x81); // 设置对比度控制
    SSD1306_WriteCommand(0xFF); // 对比度值 (0x00-0xFF)
    
    SSD1306_WriteCommand(0xA1); // 设置段重映射 (A0:正常; A1:反向)
    
    SSD1306_WriteCommand(0xA6); // 设置正常/反向显示 (A6:正常; A7:反向)
    
    SSD1306_WriteCommand(0xA8); // 设置多路复用比
    SSD1306_WriteCommand(0x3F); // 1/64 duty (0x0F-0x3F)
    
    SSD1306_WriteCommand(0xA4); // 输出跟随RAM内容
    
    SSD1306_WriteCommand(0xD3); // 设置显示偏移
    SSD1306_WriteCommand(0x00); // 无偏移
    
    SSD1306_WriteCommand(0xD5); // 设置显示时钟分频比/振荡器频率
    SSD1306_WriteCommand(0xF0); // 分频比=1, 振荡器频率最高
    
    SSD1306_WriteCommand(0xD9); // 设置预充电周期
    SSD1306_WriteCommand(0x22); // Phase1=2 DCLK, Phase2=2 DCLK
    
    SSD1306_WriteCommand(0xDA); // 设置COM引脚硬件配置
    SSD1306_WriteCommand(0x12); // 替代COM引脚配置
    
    SSD1306_WriteCommand(0xDB); // 设置VCOMH取消选择级别
    SSD1306_WriteCommand(0x20); // 0x20: 0.77xVCC
    
    SSD1306_WriteCommand(0x8D); // 设置电荷泵
    SSD1306_WriteCommand(0x14); // 使能电荷泵
    
    SSD1306_WriteCommand(0xAF); // 开启显示
    
    // 清空屏幕
    SSD1306_Clear();
    SSD1306_UpdateScreen();
    
    printf("SSD1306 OLED显示屏初始化完成\r\n");
}

// 清空屏幕
void SSD1306_Clear(void) {
    memset(SSD1306_Buffer, 0x00, sizeof(SSD1306_Buffer));
    SSD1306_CursorX = 0;
    SSD1306_CursorY = 0;
}

// 更新显示
void SSD1306_UpdateScreen(void) {
    uint8_t i, j;
    
    for (i = 0; i < 8; i++) {
        SSD1306_WriteCommand(0xB0 + i); // 设置页地址 (0-7)
        SSD1306_WriteCommand(0x00);     // 设置低列地址
        SSD1306_WriteCommand(0x10);     // 设置高列地址
        
        // 发送数据
        I2C_GenerateSTART(I2C1, ENABLE);
        if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return;
        
        I2C_Send7bitAddress(I2C1, SSD1306_I2C_ADDR >> 1, I2C_Direction_Transmitter);
        if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return;
        
        I2C_SendData(I2C1, SSD1306_DATA);
        if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return;
        
        for (j = 0; j < 128; j++) {
            I2C_SendData(I2C1, SSD1306_Buffer[j + (i * 128)]);
            if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return;
        }
        
        I2C_GenerateSTOP(I2C1, ENABLE);
    }
}

// 设置光标位置
void SSD1306_SetCursor(uint8_t x, uint8_t y) {
    SSD1306_CursorX = x;
    SSD1306_CursorY = y;
}

// 绘制像素点
void SSD1306_DrawPixel(uint8_t x, uint8_t y, uint8_t color) {
    if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) {
        return;
    }
    
    if (color) {
        SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= (1 << (y % 8));
    } else {
        SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8));
    }
}

// 绘制线条
void SSD1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color) {
    int dx = abs(x2 - x1);
    int dy = abs(y2 - y1);
    int sx = (x1 < x2) ? 1 : -1;
    int sy = (y1 < y2) ? 1 : -1;
    int err = dx - dy;
    
    while (1) {
        SSD1306_DrawPixel(x1, y1, color);
        
        if (x1 == x2 && y1 == y2) break;
        
        int e2 = 2 * err;
        if (e2 > -dy) {
            err -= dy;
            x1 += sx;
        }
        if (e2 < dx) {
            err += dx;
            y1 += sy;
        }
    }
}

// 绘制矩形
void SSD1306_DrawRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) {
    SSD1306_DrawLine(x, y, x + w, y, color);           // 上边
    SSD1306_DrawLine(x, y + h, x + w, y + h, color);   // 下边
    SSD1306_DrawLine(x, y, x, y + h, color);           // 左边
    SSD1306_DrawLine(x + w, y, x + w, y + h, color);   // 右边
}

// 绘制位图
void SSD1306_DrawBitmap(uint8_t x, uint8_t y, const uint8_t *bitmap, uint8_t w, uint8_t h) {
    int8_t byteWidth = (w + 7) / 8;
    uint8_t byte = 0;
    
    for (uint8_t j = 0; j < h; j++, y++) {
        for (uint8_t i = 0; i < w; i++) {
            if (i & 7) byte >>= 1;
            else byte = bitmap[j * byteWidth + i / 8];
            
            SSD1306_DrawPixel(x + i, y, byte & 0x01);
        }
    }
}

// 6x8字体数据 (简化版，只包含ASCII字符)
static const uint8_t Font6x8[][6] = {
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 空格
    {0x00, 0x00, 0x5F, 0x00, 0x00, 0x00}, // !
    {0x00, 0x07, 0x00, 0x07, 0x00, 0x00}, // "
    // ... 这里应该包含完整的ASCII字符集
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}  // ~
};

// 写入字符
void SSD1306_WriteChar(char ch, FontDef font) {
    uint32_t i, b, j;
    
    // 检查边界
    if (SSD1306_WIDTH <= (SSD1306_CursorX + 6) || SSD1306_HEIGHT <= (SSD1306_CursorY + 8)) {
        return;
    }
    
    // 根据字体选择字符数据 (这里简化处理)
    if (ch >= 32 && ch <= 126) { // ASCII字符范围
        for (i = 0; i < 6; i++) {
            uint8_t line = Font6x8[ch - 32][i];
            for (j = 0; j < 8; j++) {
                if (line & (1 << j)) {
                    SSD1306_DrawPixel(SSD1306_CursorX + i, SSD1306_CursorY + j, 1);
                } else {
                    SSD1306_DrawPixel(SSD1306_CursorX + i, SSD1306_CursorY + j, 0);
                }
            }
        }
    }
    
    // 更新光标位置
    SSD1306_CursorX += 6;
}

// 写入字符串
void SSD1306_WriteString(char *str, FontDef font) {
    while (*str) {
        if (*str == '\n') {
            SSD1306_CursorY += 8;
            SSD1306_CursorX = 0;
        } else if (*str == '\r') {
            SSD1306_CursorX = 0;
        } else {
            SSD1306_WriteChar(*str, font);
        }
        str++;
    }
}
